package com.nuorui.module.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuorui.common.core.domain.ResponseDTO;
import com.nuorui.common.utils.SmartBeanUtil;
import com.nuorui.module.system.domain.form.MenuForm;
import com.nuorui.module.system.domain.query.MenuQueryForm;
import com.nuorui.module.system.domain.vo.MenuTreeVO;
import com.nuorui.module.system.domain.vo.MenuVO;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Service;
import com.nuorui.module.system.mapper.MenuMapper;
import com.nuorui.module.system.domain.entity.MenuEntity;
import com.nuorui.module.system.service.MenuService;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 菜单表
 *
 * @author
 * @date 2021-12-14 09:32:44
 */
@Service
@AllArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper, MenuEntity> implements MenuService {


    @Override
    public ResponseDTO getMenuGroup(MenuQueryForm queryForm) {

        List<MenuVO> menuVOList = baseMapper.selectMenuList(queryForm);
        //根据ParentId进行分组
        Map<Long, List<MenuVO>> parentMap = menuVOList.stream().collect(Collectors.groupingBy(MenuVO::getParentId, Collectors.toList()));
        return ResponseDTO.ok(filterNoParentMenu(parentMap, NumberUtils.LONG_ZERO));
    }

    private List<MenuVO> filterNoParentMenu(Map<Long, List<MenuVO>> parentMap, Long parentId) {

        List<MenuVO> result = new ArrayList<>();
        List<MenuVO> children = parentMap.getOrDefault(parentId, Collections.emptyList());

        for (MenuVO child : children) {
            result.add(child);
            result.addAll(filterNoParentMenu(parentMap, child.getMenuId()));
        }
        return result;
    }

    @Override
    public ResponseDTO<List<MenuTreeVO>> getMenuTree(MenuQueryForm queryForm) {
        List<MenuVO> menuVOList = baseMapper.selectMenuList(queryForm);
        //根据ParentId进行分组
        Map<Long, List<MenuVO>> parentMap = menuVOList.stream().collect(Collectors.groupingBy(MenuVO::getParentId, Collectors.toList()));
        List<MenuTreeVO> menuTreeVOList = buildMenuTree(parentMap, NumberUtils.LONG_ZERO);
        return ResponseDTO.ok(menuTreeVOList);
    }

    List<MenuTreeVO> buildMenuTree(Map<Long, List<MenuVO>> parentMap, Long parentId) {
        List<MenuVO> currentList = parentMap.getOrDefault(parentId, new ArrayList<>());
        List<MenuTreeVO> result = new ArrayList<>();

        for (MenuVO menu : currentList) {
            MenuTreeVO treeNode = SmartBeanUtil.copy(menu, MenuTreeVO.class);
            List<MenuTreeVO> children = buildMenuTree(parentMap, menu.getMenuId());
            if (!children.isEmpty()) {
                treeNode.setChildren(children);
            }
            result.add(treeNode);
        }
        return result;
    }

    @Override
    public ResponseDTO saveMenu(MenuForm menuForm) {

        // 校验菜单名称是否重复
        MenuVO nameConflict = baseMapper.getByMenuName(menuForm.getMenuName(), menuForm.getParentId());
        if (nameConflict != null) {
            return ResponseDTO.userErrorParam("菜单名称已存在");
        }

        // 校验前端权限标识是否重复
        MenuVO permsConflict = baseMapper.getByWebPerms(menuForm.getWebPerms());
        if (permsConflict != null) {
            return ResponseDTO.userErrorParam("前端权限字符串已存在");
        }

        // 保存菜单
        MenuEntity entity = SmartBeanUtil.copy(menuForm, MenuEntity.class);
        baseMapper.insert(entity);

        return ResponseDTO.ok();
    }

    /**
     * 更新菜单
     */
    @Override
    public ResponseDTO updateMenu(Long menuId, MenuForm menuForm) {
        // 校验菜单是否存在
        MenuEntity existingMenu = baseMapper.selectById(menuId);
        if (existingMenu == null) {
            return ResponseDTO.userErrorParam("菜单不存在");
        }
        //校验菜单名称
        ResponseDTO<String> checkResponse = checkUniqueness(menuId, menuForm.getMenuName(), menuForm.getParentId(), menuForm.getWebPerms());
        if (!checkResponse.getOk()) {
            return checkResponse;
        }

        // 更新菜单
        MenuEntity entity = SmartBeanUtil.copy(menuForm, MenuEntity.class);
        entity.setMenuId(menuId);
        baseMapper.updateById(entity);

        return ResponseDTO.ok();
    }

    private ResponseDTO<String> checkUniqueness(Long menuId, String menuName, Long parentId, String webPerms) {

        if (menuId.equals(parentId)) {
            return ResponseDTO.userErrorParam("上级菜单不能为自己");
        }
        // 检查名称是否冲突
        MenuVO nameConflict = baseMapper.getByMenuName(menuName, parentId);
        if (nameConflict != null && !Objects.equals(nameConflict.getMenuId(), menuId)) {
            return ResponseDTO.userErrorParam("菜单名称已存在");
        }
        // 检查权限标识是否冲突
        MenuVO permsConflict = baseMapper.getByWebPerms(webPerms);
        if (permsConflict != null && !Objects.equals(permsConflict.getMenuId(), menuId)) {
            return ResponseDTO.userErrorParam("前端权限字符串已存在");
        }
        return ResponseDTO.ok();
    }

    /**
     * 批量删除菜单
     */
    @Override
    public ResponseDTO batchDelete(List<Long> menuIdList) {
        if (CollectionUtils.isEmpty(menuIdList)) {
            return ResponseDTO.userErrorParam("所选菜单不能为空");
        }
        baseMapper.deleteByMenuIdList(menuIdList);
        //孩子节点也需要删除
        recursiveDeleteChildren(menuIdList);

        return ResponseDTO.ok();
    }

    private void recursiveDeleteChildren(List<Long> menuIdList) {
        List<Long> childrenMenuIdList = baseMapper.selectChildIdsByMenuIdList(menuIdList);
        if (CollectionUtil.isEmpty(childrenMenuIdList)) {
            return;
        }
        baseMapper.deleteByMenuIdList(childrenMenuIdList);
        recursiveDeleteChildren(childrenMenuIdList);
    }
}
